home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
016
/
source.files
/
seeilbm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
20KB
|
618 lines
/*****************************************************************
*
* Read an ILBM file and display as a screen/window until closed.
* Simulated close gadget in upper left corner of window.
* Clicking below title bar area toggles screen bar for dragging.
*
* By Carolyn Scheppner CBM 03/15/86
*
* Based on early ShowILBM.c 11/12/85
* By Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
* This software is in the public domain.
*
* >>NOTE<<: This example must be linked with additional IFF rtn files.
* See linkage information below.
*
* The IFF reader portion is essentially a recursive-descent parser.
* This program will look into a CAT or LIST to find a FORM ILBM, but it
* won't look inside another FORM type for a nested FORM ILBM.
*
* The display portion is specific to the Commodore Amiga computer.
*
* Linkage Information:
*
* FROM LStartup.obj, SeeILBM.o, iffr.o, ilbmr.o, unpacker.o
* TO SeeILBM
* LIBRARY LC.lib, Amiga.lib
*
**************************************************************************/
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <graphics/gfxbase.h>
#include <graphics/rastport.h>
#include <graphics/gfx.h>
#include <graphics/view.h>
#include <workbench/startup.h>
#include <intuition/intuition.h>
#include <lattice/stdio.h>
#include "iff/ilbm.h"
/* This example's max number of planes in a bitmap. Could use MaxAmDepth. */
#define EXDepth 5
#define maxColorReg (1<<EXDepth)
#define MIN(a,b) ((a)<(b)?(a):(b))
#define SafeFreeMem(p,q) {if(p)FreeMem(p,q);}
/* Define the size of a temp buffer used in unscrambling the ILBM rows.*/
#define bufSz 512
/* general usage pointers */
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct IntuiMessage *message;
/* Globals for displaying an image */
struct Screen *screen1;
struct Window *window1;
struct RastPort *rport1;
struct ViewPort *vport1;
struct BitMap tBitMap; /* Temp BitMap struct for small pics */
/* For WorkBench startup */
extern struct WBStartup *WBenchMsg;
BOOL fromWB;
struct FileLock *startLock, *newLock;
/* Other globals */
int i, error;
BYTE c;
BOOL TBtoggle, Done;
ULONG class, code, pBytes;
/* Structures for new Screen, new Window */
struct TextAttr TextFont = {
"topaz.font", /* Font Name */
TOPAZ_EIGHTY, /* Font Height */
FS_NORMAL, /* Style */
FPF_ROMFONT, /* Preferences */
};
struct NewScreen ns = {
0, 0, /* LeftEdge and TopEdge */
0, 0, /* Width and Height */
0, /* Depth */
-1, -1, /* DetailPen and BlockPen */
NULL, /* Special display modes */
CUSTOMSCREEN, /* Screen Type */
&TextFont, /* Use my font */
NULL, /* Title */
NULL, /* No gadgets yet */
NULL, /* Ptr to CustomBitmap */
};
struct NewWindow nw = {
0, 0, /* LeftEdge and TopEdge */
0, 0, /* Width and Height */
-1, -1, /* DetailPen and BlockPen */
MOUSEBUTTONS, /* IDCMP Flags */
ACTIVATE
|BACKDROP
|BORDERLESS, /* Flags */
NULL, NULL, /* Gadget and Image pointers */
NULL, /* Title string */
NULL, /* Put Screen ptr here */
NULL, /* SuperBitMap pointer */
0, 0, /* MinWidth and MinHeight */
0, 0, /* MaxWidth and MaxHeight */
CUSTOMSCREEN, /* Type of window */
};
USHORT allBgColor[32];
/* Message strings for IFFP codes. */
char MsgOkay[] = {"(IFF_OKAY) No FORM ILBM in the file." };
char MsgEndMark[] = {"(END_MARK) How did you get this message?" };
char MsgDone[] = {"(IFF_DONE) All done."};
char MsgDos[] = {"(DOS_ERROR) The DOS returned an error." };
char MsgNot[] = {"(NOT_IFF) Not an IFF file." };
char MsgNoFile[] = {"(NO_FILE) No such file found." };
char MsgClientError[] = {"(CLIENT_ERROR) ShowILBM bug or insufficient RAM."};
char MsgForm[] = {"(BAD_FORM) A malformed FORM ILBM." };
char MsgShort[] = {"(SHORT_CHUNK) A malformed FORM ILBM." };
char MsgBad[] = {"(BAD_IFF) A mangled IFF file." };
/* THESE MUST APPEAR IN RIGHT ORDER!! */
char *IFFPMessages[-LAST_ERROR+1] = {
/*IFF_OKAY*/ MsgOkay,
/*END_MARK*/ MsgEndMark,
/*IFF_DONE*/ MsgDone,
/*DOS_ERROR*/ MsgDos,
/*NOT_IFF*/ MsgNot,
/*NO_FILE*/ MsgNoFile,
/*CLIENT_ERROR*/ MsgClientError,
/*BAD_FORM*/ MsgForm,
/*SHORT_CHUNK*/ MsgShort,
/*BAD_IFF*/ MsgBad
};
/*------------ ILBM reader -----------------------------------------------*/
/* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
* We allocate one of these on the stack for every LIST or FORM encountered
* in the file and use it to hold BMHD & CMAP properties. We also allocate
* an initial one for the whole file.
* We allocate a new GroupContext (and initialize it by OpenRIFF or
* OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
* just a context for reading (nested) chunks.
*
* If we were to scan the entire example file outlined below:
* reading proc(s) new new
*
* --whole file-- ReadPicture+ReadIFF GroupContext ILBMFrame
* CAT ReadICat GroupContext
* LIST GetLiILBM+ReadIList GroupContext ILBMFrame
* PROP ILBM GetPrILBM GroupContext
* CMAP GetCMAP
* BMHD GetBMHD
* FORM ILBM GetFoILBM GroupContext ILBMFrame
* BODY GetBODY
* FORM ILBM GetFoILBM GroupContext ILBMFrame
* BODY GetBODY
* FORM ILBM GetFoILBM GroupContext ILBMFrame
*/
typedef struct {
ClientFrame clientFrame;
UBYTE foundBMHD;
UBYTE nColorRegs;
BitMapHeader bmHdr;
Color4 colorMap[maxColorReg];
/* If you want to read any other property chunks, e.g. GRAB or CAMG, add
* fields to this record to store them. */
} ILBMFrame;
/* NOTE: For a simple version of this program, set Fancy to 0.
* That'll compile a program that skips all LISTs and PROPs in the input
* file. It will look in CATs for FORMs ILBM. That's suitable for most uses.
*
* For a fancy version that handles LISTs and PROPs, set Fancy to 1. */
#define Fancy 1
/* Modified by C. Scheppner */
/* iFrame made global - moved from ReadPicture() */
/* ilbmFrame made global - moved from GetFoILBM() */
ILBMFrame iFrame; /* top level client frame */
ILBMFrame ilbmFrame; /* global bitmap frame */
/** main() ****************************************************************/
main(argc, argv)
int argc;
char **argv;
{
LONG file;
IFFP iffp = NO_FILE;
struct WBArg *arg;
char *filename;
fromWB = (argc==0) ? TRUE : FALSE;
if(argc>1) /* Passed filename via command line */
{
filename = argv[1];
}
else if ((argc==0)&&(WBenchMsg->sm_NumArgs > 1))
{ /* Passed filename via WorkBench */
arg = WBenchMsg->sm_ArgList;
arg++;
filename = (char *)arg->wa_Name;
newLock = (struct FileLock *)arg->wa_Lock;
startLock = (struct FileLock *)CurrentDir(newLock);
}
else if (argc==1) /* From CLI but no filename */
cleanexit("Usage: 'SeeILBM filename'\n");
else /* From WB but no filename */
cleanexit("\nClick ONCE on SeeILBM\nSHIFT and DoubleClick on Pic\n");
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
cleanexit("Can't open graphics library\n");
if(!(IntuitionBase=
(struct IntuitionBase *)OpenLibrary("intuition.library",0)))
cleanexit("Can't open graphics library\n");
if(file = Open(filename, MODE_OLDFILE))
{
printf("\nCLICK PIC TOP LEFT TO END DISPLAY\n");
printf("CLICK LOWER TO TOGGLE DRAG BAR\n");
Delay(150); /* wait about 3 seconds to give person time to read it */
iffp = ReadPicture(file);
Close(file);
if (iffp == IFF_DONE)
{
error = DisplayPic(&ilbmFrame);
if(error) cleanexit("Can't open screen or window\n");
TBtoggle = FALSE; /* Title bar toggle */
Done = FALSE; /* Close flag */
while (!Done)
{
if(1<<window1->UserPort->mp_SigBit) chkmsg();
}
}
else cleanexit(IFFPMessages[-iffp]);
}
else cleanexit("Picture file not found.\n");
cleanup();
}
chkmsg()
{
while(message=(struct IntuiMessage *)GetMsg(window1->UserPort))
{
class = message->Class;
code = message->Code;
ReplyMsg(message);
switch(class)
{
case MOUSEBUTTONS:
if ((code == SELECTDOWN)&&
(window1->MouseX < 10)&&(window1->MouseY<10))
{
Done = TRUE;
}
else if ((code == SELECTDOWN)&&
(window1->MouseY>10)&&(TBtoggle==FALSE))
{
TBtoggle = TRUE;
ShowTitle(screen1,TRUE);
}
else if ((code == SELECTDOWN)&&
(window1->MouseY>10)&&(TBtoggle==TRUE))
{
TBtoggle = FALSE;
ShowTitle(screen1,FALSE);
}
break;
default:
printf("Unknown IDCMP message\n");
}
}
}
cleanexit(errstr)
char *errstr;
{
printf("\n %s \n",errstr);
cleanup();
if (fromWB) /* Wait so user can read messages */
{
printf("\nPRESS RETURN TO CLOSE THIS WINDOW\n");
while ((c=getchar()) != '\n');
}
exit();
}
cleanup()
{
/* tBitMap planes were deallocated in DisplayPic() */
if (window1) CloseWindow(window1);
if (screen1) CloseScreen(screen1);
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (GfxBase) CloseLibrary(GfxBase);
if (newLock != startLock) CurrentDir(startLock);
}
/** getBitMap() *********************************************************
*
* Open screen or temp bitmap.
* Returns ptr destBitMap or 0 = error
*
*************************************************************************/
struct BitMap *getBitMap(ptilbmFrame)
ILBMFrame *ptilbmFrame;
{
int i, nPlanes, plsize;
SHORT sWidth, sHeight, dWidth, dHeight;
struct BitMap *destBitMap;
sWidth = ptilbmFrame->bmHdr.w;
sHeight = ptilbmFrame->bmHdr.h;
dWidth = ptilbmFrame->bmHdr.pageWidth;
dHeight = ptilbmFrame->bmHdr.pageHeight;
nPlanes = MIN(ptilbmFrame->bmHdr.nPlanes, EXDepth);
for (i = 0; i < ptilbmFrame->nColorRegs; i++)
{
allBgColor[i] = ptilbmFrame->colorMap[0];
}
ns.Width = dWidth;
ns.Height = dHeight;
ns.Depth = nPlanes;
if (ptilbmFrame->bmHdr.pageWidth <= 320)
ns.ViewModes = 0;
else
ns.ViewModes = HIRES;
if (ptilbmFrame->bmHdr.pageHeight > 200)
ns.ViewModes |= LACE;
if ((screen1 = (struct Screen *)OpenScreen(&ns))==NULL) return(0);
vport1 = &screen1->ViewPort;
LoadRGB4(vport1, &allBgColor[0], ptilbmFrame->nColorRegs);
nw.Width = dWidth;
nw.Height = dHeight;
nw.Screen = screen1;
if ((window1 = (struct Window *)OpenWindow(&nw))==NULL) return(0);
ShowTitle(screen1, FALSE);
if ((sWidth == dWidth) && (sHeight == dHeight))
{
destBitMap = (struct BitMap *)screen1->RastPort.BitMap;
}
else
{
InitBitMap( &tBitMap,
nPlanes,
sWidth,
sHeight);
plsize = RowBytes(ptilbmFrame->bmHdr.w) * ptilbmFrame->bmHdr.h;
if (tBitMap.Planes[0] =
(PLANEPTR)AllocMem(nPlanes * plsize, MEMF_CHIP))
{
for (i = 1; i < nPlanes; i++)
tBitMap.Planes[i] = (PLANEPTR)tBitMap.Planes[0] + plsize*i;
destBitMap = &tBitMap;
}
else
{
return(0); /* can't allocate temp BitMap */
}
}
return(destBitMap); /* destBitMap allocated */
}
/** DisplayPic() *********************************************************
*
* Display loaded bitmap. If tBitMap, first transfer to screen.
*
*************************************************************************/
DisplayPic(ptilbmFrame)
ILBMFrame *ptilbmFrame;
{
int i, row, byte, nrows, nbytes;
struct BitMap *tbp, *sbp; /* temp and screen BitMap ptrs */
UBYTE *tpp, *spp; /* temp and screen plane ptrs */
if (tBitMap.Planes[0]) /* transfer from tBitMap if nec. */
{
tbp = &tBitMap;
sbp = screen1->RastPort.BitMap;
nrows = MIN(tbp->Rows, sbp->Rows);
nbytes = MIN(tbp->BytesPerRow, sbp->BytesPerRow);
for (i = 0; i < sbp->Depth; i++)
{
tpp = (UBYTE *)tbp->Planes[i];
spp = (UBYTE *)sbp->Planes[i];
for (row = 0; row < nrows; row++)
{
tpp = tbp->Planes[i] + (row * tbp->BytesPerRow);
spp = sbp->Planes[i] + (row * sbp->BytesPerRow);
for (byte = 0; byte < nbytes; byte++)
{
*spp++ = *tpp++;
}
}
}
/* Can now deallocate the temp BitMap */
FreeMem(tBitMap.Planes[0],
tBitMap.BytesPerRow * tBitMap.Rows * tBitMap.Depth);
}
vport1 = &screen1->ViewPort;
LoadRGB4(vport1, ptilbmFrame->colorMap, ptilbmFrame->nColorRegs);
return(0);
}
/** GetLiILBM() **********************************************************
*
* Called via ReadPicture to handle every LIST encountered in an IFF file.
*
*************************************************************************/
#if Fancy
IFFP GetLiILBM(parent)
GroupContext *parent; {
ILBMFrame newFrame; /* allocate a new Frame */
newFrame = *(ILBMFrame *)parent->clientFrame; /* copy parent frame */
return( ReadIList(parent, (ClientFrame *)&newFrame) );
}
#endif
/** GetPrILBM() **********************************************************
*
* Called via ReadPicture to handle every PROP encountered in an IFF file.
* Reads PROPs ILBM and skips all others.
*
*************************************************************************/
#if Fancy
IFFP GetPrILBM(parent)
GroupContext *parent; {
/*compilerBug register*/ IFFP iffp;
GroupContext propContext;
ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
if (parent->subtype != ID_ILBM)
return(IFF_OKAY); /* just continue scaning the file */
iffp = OpenRGroup(parent, &propContext);
CheckIFFP();
do switch (iffp = GetPChunkHdr(&propContext)) {
case ID_BMHD: {
ilbmFrame->foundBMHD = TRUE;
iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
break; }
case ID_CMAP: {
ilbmFrame->nColorRegs = maxColorReg; /* room for this many */
iffp = GetCMAP( &propContext, (WORD *)ilbmFrame->colorMap,
&ilbmFrame->nColorRegs);
break; }
} while (iffp >= IFF_OKAY);/* loop if valid ID of ignored chunk or
* subrtn returned IFF_OKAY (no errors).*/
CloseRGroup(&propContext);
return(iffp == END_MARK ? IFF_OKAY : iffp);
}
#endif
/** GetFoILBM() **********************************************************
*
* Called via ReadPicture to handle every FORM encountered in an IFF file.
* Reads FORMs ILBM and skips all others.
* Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
* finds no BODY or if it has no BMHD to decode the BODY.
*
* Once we find a BODY chunk, we'll allocate the BitMap and read the image.
*
* Modified by C. Scheppner: ilbmFrame moved above main making it
* global so main can call DisplayPic()
*
*************************************************************************/
IFFP GetFoILBM(parent)
GroupContext *parent;
{
IFFP iffp;
GroupContext formContext;
BYTE buffer[bufSz];
struct BitMap *destBitMap;
if (parent->subtype != ID_ILBM)
return(IFF_OKAY); /* just continue scaning the file */
ilbmFrame = *(ILBMFrame *)parent->clientFrame;
iffp = OpenRGroup(parent, &formContext);
CheckIFFP();
do switch (iffp = GetFChunkHdr(&formContext)) {
case ID_BMHD: {
ilbmFrame.foundBMHD = TRUE;
iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
break; }
case ID_CMAP: {
ilbmFrame.nColorRegs = maxColorReg; /* we have room for this many */
iffp = GetCMAP(&formContext, (WORD *)ilbmFrame.colorMap,
&ilbmFrame.nColorRegs);
break; }
case ID_BODY: {
if (!ilbmFrame.foundBMHD) return(BAD_FORM); /* No BMHD chunk! */
if(destBitMap=(struct BitMap *)getBitMap(&ilbmFrame))
{
iffp = GetBODY( &formContext,
destBitMap,
NULL,
&ilbmFrame.bmHdr,
buffer,
bufSz);
if (iffp == IFF_OKAY) iffp = IFF_DONE; /* Eureka */
}
else
iffp = CLIENT_ERROR; /* not enough RAM for the bitmap */
break; }
case END_MARK: {
iffp = BAD_FORM;
break; }
} while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk or a
* subroutine returned IFF_OKAY (no errors).*/
if (iffp != IFF_DONE) return(iffp);
CloseRGroup(&formContext);
return(iffp);
}
/** Notes on extending GetFoILBM *****************************************
*
* To read more kinds of chunks, just add clauses to the switch statement.
* To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
* the switch statement in GetPrILBM, too.
*
* To read a FORM type that contains a variable number of data chunks--e.g.
* a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
* an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
* case do whatever cleanup you need.
*
*************************************************************************/
/** ReadPicture() ********************************************************
*
* Read a picture from an IFF file, given a file handle open for reading.
*
* Modified by Carolyn Scheppner CBM 03-86
* iFrame made global (above main)
* Close(file) moved to main
*
*************************************************************************/
IFFP ReadPicture(file)
LONG file;
{
IFFP iffp = IFF_OKAY;
#if Fancy
iFrame.clientFrame.getList = GetLiILBM;
iFrame.clientFrame.getProp = GetPrILBM;
#else
iFrame.clientFrame.getList = SkipGroup;
iFrame.clientFrame.getProp = SkipGroup;
#endif
iFrame.clientFrame.getForm = GetFoILBM;
iFrame.clientFrame.getCat = ReadICat ;
/* Initialize the top-level client frame's property settings to the
* program-wide defaults. This example just records that we haven't read
* any BMHD property or CMAP color registers yet. For the color map, that
* means the default is to leave the machine's color registers alone.
* If you want to read a property like GRAB, init it here to (0, 0). */
iFrame.foundBMHD = FALSE;
iFrame.nColorRegs = 0;
iffp = ReadIFF(file, (ClientFrame *)&iFrame);
return(iffp);
}